package com.flashidea.zddziot.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.flashidea.zddziot.R;

/**
 * 自定义圆形旋转音量调节按钮
 * 
 * @author jinhui
 */
public class RoundVolumeView extends View {

	private Paint paint;
	/**
	 * 旋转点坐标
	 */
	private float x, y;
	/**
	 * 圆心坐标
	 */
	private float cx, cy;
	/**
	 * 半径
	 */
	private float radius;
	/**
	 * 旋转点
	 */
	private Bitmap pointBitmap;
	/**
	 * 背景
	 */
	private Bitmap backgroundBitmap;
	/**
	 * 旋转点所在位置角度
	 */
	private int angle = -90;
	/**
	 * 角度变化回调监听
	 */
	private OnAngleChangeListener listener;
	/**
	 * 刻度颜色
	 */
	private int rateColor;
	/**
	 * 刻度大小
	 */
	private float rateSize;
	/**
	 * 长刻度线的长度
	 */
	private float rateLong;
	/**
	 * 短刻度线的长度
	 */
	private float rateShort;
	private float density;

	/**
	 * 刻度颜色
	 */
	public int getRateColor() {
		return rateColor;
	}

	/**
	 * 刻度颜色
	 */
	public void setRateColor(int color) {
		this.rateColor = color;
	}

	/**
	 * 刻度大小
	 */
	public float getRateSize() {
		return rateSize;
	}

	/**
	 * 刻度大小
	 */
	public void setRateSize(float size) {
		this.rateSize = size * density;
	}

	/**
	 * 刻度长度
	 */
	public float getRateLong() {
		return rateLong;
	}

	public float getRateShort() {
		return rateShort;
	}

	public void setRateShort(float rateShort) {
		this.rateShort = rateShort;
	}

	/**
	 * 刻度长度
	 */
	public void setRateLong(float rateLong) {
		this.rateLong = rateLong;
	}

	/**
	 * 设置角度变化回调监听
	 * 
	 * @param listener
	 */
	public void setOnAngleChangeListener(OnAngleChangeListener listener) {
		this.listener = listener;
	}

	/**
	 * 设置旋转点图片
	 */
	public void setPointBitmap(Bitmap bitmap) {
		this.pointBitmap = bitmap;
		invalidate();
	}

	/**
	 * 设置背景图片
	 */
	public void setBackgroundBitmap(Bitmap bitmap) {
		this.backgroundBitmap = bitmap;
		invalidate();
	}

	/**
	 * 获取角度
	 */
	public double getAngle() {
		return angle;
	}

	/**
	 * 设置角度
	 */
	public void setAngle(int angle, boolean notifi) {
		this.angle = angle;
		rotateButtons(0, notifi);
	}

	public RoundVolumeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
		super(context, attrs, defStyleAttr, defStyleRes);
		init(context, attrs);
	}

	public RoundVolumeView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context, attrs);
	}

	public RoundVolumeView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context, attrs);
	}

	private void init(Context context, AttributeSet attrs) {
		density = getResources().getDisplayMetrics().density;
		/* 这里取得declare-styleable集合 */
		TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
		/* 这里从集合里取出相对应的属性值,第二参数是如果使用者没用配置该属性时所用的默认值 */
		rateColor = typeArray.getColor(R.styleable.CustomView_rateColor, Color.WHITE);
		rateSize = typeArray.getDimension(R.styleable.CustomView_rateSize, 1);
		rateLong = typeArray.getDimension(R.styleable.CustomView_longLine, 10);
		rateShort = rateLong / 2;
		int resourceId = typeArray.getResourceId(R.styleable.CustomView_backgroundDrawable,
			R.drawable.rotary_knob);
		backgroundBitmap = BitmapFactory.decodeResource(getResources(), resourceId);
		resourceId = typeArray.getResourceId(R.styleable.CustomView_volumeDrawable,
			R.drawable.circle);
		pointBitmap = BitmapFactory.decodeResource(getResources(), resourceId);
		/* 关闭资源 */
		typeArray.recycle();
		paint = new Paint();
		paint.setColor(rateColor);
		paint.setAntiAlias(true);
		paint.setStrokeWidth(rateSize);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int measuredWidth = getMeasuredWidth();
		int measuredHeight = getMeasuredHeight();
		if (measuredWidth > measuredHeight) {
			setMeasuredDimension(measuredHeight, measuredHeight);
		} else {
			setMeasuredDimension(measuredWidth, measuredWidth);
		}
		cx = getMeasuredWidth() / 2;
		cy = getMeasuredHeight() / 2;
		// 初始化半径
		radius = cx < cy ? cx - cx / 5f : cy - cy / 5f;
		computeCoordinates();
	}

	@Override
	public void onDraw(Canvas canvas) {
		drawLines(canvas);
		drawBackground(canvas);
		drawPoint(canvas);
	}

	/**
	 * 画刻度
	 * 
	 * @param canvas
	 */
	private void drawLines(Canvas canvas) {
		canvas.save();
		Paint paint = new Paint(this.paint);
		paint.setStyle(Style.STROKE);
		PathEffect effect = new DashPathEffect(new float[] { 8 * density, 10 * density,
				8 * density, 10 * density }, 2);
		paint.setPathEffect(effect);
		float r = 2 * density;
		RectF oval = new RectF(cx - radius - r, cy - radius - r, cx + radius + r, cy + radius + r);
		canvas.drawArc(oval, 135, 270, false, paint);
		float lx = cx + (float) ((radius + rateLong + r) * Math.cos(Math.toRadians(135)));
		float ly = cy + (float) ((radius + rateLong + r) * Math.sin(Math.toRadians(135)));
		canvas.drawLine(cx, cy, lx, ly, paint);
		lx = cx + (float) ((radius + rateLong + r) * Math.cos(Math.toRadians(45)));
		ly = cy + (float) ((radius + rateLong + r) * Math.sin(Math.toRadians(45)));
		canvas.drawLine(cx, cy, lx, ly, paint);
		canvas.restore();
	}

//	private void drawLines(Canvas canvas) {
//		int count = -1;
//		for (int i = 0; i < 360; i += 20) {
//			float lx, ly;
//			if (++count % 2 == 0) {
//				paint.setStrokeWidth((float) (rateSize * 1.2));
//				lx = cx + (float) ((radius + rateLong) * Math.cos(Math.toRadians(i)));
//				ly = cy + (float) ((radius + rateLong) * Math.sin(Math.toRadians(i)));
//			} else {
//				paint.setStrokeWidth((float) (rateSize * 0.8));
//				lx = cx + (float) ((radius + rateShort) * Math.cos(Math.toRadians(i)));
//				ly = cy + (float) ((radius + rateShort) * Math.sin(Math.toRadians(i)));
//			}
//			canvas.drawLine(cx, cy, lx, ly, paint);
//		}
//	}
	/**
	 * 画旋转点
	 * 
	 * @param canvas
	 */
	private void drawPoint(Canvas canvas) {
		if (pointBitmap != null) {
			Rect dst = new Rect();
			dst.left = (int) (x - pointBitmap.getWidth() / 2);
			dst.right = (int) (x + pointBitmap.getWidth() / 2);
			dst.top = (int) (y - pointBitmap.getHeight() / 2);
			dst.bottom = (int) (y + pointBitmap.getHeight() / 2);
			canvas.drawBitmap(pointBitmap, null, dst, paint);
		}
	}

	/**
	 * 画按钮背景
	 * 
	 * @param canvas
	 */
	private void drawBackground(Canvas canvas) {
		if (backgroundBitmap != null) {
			Rect dst = new Rect();
			dst.left = (int) (cx - radius);
			dst.right = (int) (cx + radius);
			dst.top = (int) (cy - radius);
			dst.bottom = (int) (cy + radius);
			canvas.drawBitmap(backgroundBitmap, null, dst, paint);
		}
	}

	/**
	 * 计算坐标
	 */
	private void computeCoordinates() {
		x = cx
			+ (float) ((radius - pointBitmap.getWidth() / 1.5) * Math.cos(Math.toRadians(angle)));
		y = cy
			+ (float) ((radius - pointBitmap.getHeight() / 1.5) * Math.sin(Math.toRadians(angle)));
	}

	private double startAngle;

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		int x, y;
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			x = (int) event.getX();
			y = (int) event.getY();
			startAngle = computeCurrentAngle(x, y);
		} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
			x = (int) event.getX();
			y = (int) event.getY();
			double currentAngle = computeCurrentAngle(x, y);
			rotateButtons((int) (startAngle - currentAngle), true);
			startAngle = currentAngle;
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			x = (int) event.getX();
			y = (int) event.getY();
			double currentAngle = computeCurrentAngle(x, y);
			rotateButtons((int) (startAngle - currentAngle), true);
			startAngle = currentAngle;
		}
		return true;
	}

	/**
	 * 旋转按钮
	 */
	private void rotateButtons(int degree, boolean notifi) {
		angle -= degree;
		if (angle < 0) {
			angle += 360;
		} else if (angle >= 360) {
			angle -= 360;
		}
		if (listener != null && notifi) {
			listener.onAngleChange(this, getId(), angle, -degree);
		}
		computeCoordinates();
		invalidate();
	}

	/**
	 * 计算某点的角度
	 * 
	 * @param x
	 * @param y
	 */
	private int computeCurrentAngle(float x, float y) {
		float distance = (float) Math.sqrt(((x - cx) * (x - cx) + (y - cy) * (y - cy)));
		int degree = (int) (Math.acos((x - cx) / distance) * 180 / Math.PI);
		if (y < cy) {
			degree = -degree;
		}
		return degree;
	}
}
